angular.module('BaseControl')

.directive("calendar", ['$parse','BaseConst', 'BaseFunction', 'BaseEnum', function($parse, BaseConst, BaseFunction, BaseEnum) {
    return {
        restrict: "E",	// 指令是一个元素 (并非属性)，备选项有"A"、"E" 和 "C"， "M" ,分别代表attribute、element、class和comment（默认值为"A"）
        scope: {
            value: '=?',
            change: '&',
            blur: '&',
            keydown: '&'
        },
        templateUrl: 		// 替换HTML (使用scope中的变量)
            'modules/Base/client/views/Calendar.html',
        replace: true,			// 使用模板替换原始标记
        transclude: true,		// 不复制原始HTML内容
        controller: ['$scope', function($scope) {
            $scope.DateNow = new Date();        //弹出窗口显示的今天日期
            $scope.DisplayText;     //文本框显示的字符串格式日期
            $scope.MonthFormats = '一月,二月,三月,四月,五月,六月,七月,八月,九月,十月,十一月,十二月'.split(',');
            $scope.WindowDisplayMonth = new Date();     //设置窗口打开显示的日期

            var windowDisplayDays = new Array(42);
            var valueDateTime = new Date();
            var isSetDateValue = false;         //是否手动设置value

            var getDisplayDays = function(dateTime){
                if(dateTime == undefined || dateTime == null || dateTime == BaseConst.DateTime.Min){
                    dateTime = new Date();
                }
                $scope.WindowDisplayMonth = dateTime;
                var displayDays = new Array(42);
                var currentMonthFirstDate = new Date(dateTime.getFullYear(), dateTime.getMonth(), 1);
                var weekByFirstDay = currentMonthFirstDate.getDay();   //1号是周几

                var preMonthLastDate = new Date(currentMonthFirstDate.getFullYear(), currentMonthFirstDate.getMonth(), 0);
                var preMonthLastDay = preMonthLastDate.getDate();       //上个月的最后一天是几号

                //给系统值上个月的显示日期赋值
                for(var i=0; i<weekByFirstDay; i++){
                    displayDays[i] = new Date(preMonthLastDate.getFullYear(), preMonthLastDate.getMonth(), preMonthLastDay - weekByFirstDay + 1 + i);
                }

                var currentDays = BaseFunction.getMonthDays(dateTime);      //获取本月有多少天
                //给系统值当前月的显示日期赋值
                for(var i=0; i<currentDays; i++){
                    displayDays[i + weekByFirstDay] = new Date(currentMonthFirstDate.getFullYear(), currentMonthFirstDate.getMonth(), i + 1);
                }

                var nextMonth = new Date(currentMonthFirstDate.getFullYear(), currentMonthFirstDate.getMonth() + 1, 1);
                //给系统值下个月的显示日期赋值
                for(var i=0; i<42-currentDays-weekByFirstDay; i++){
                    displayDays[i + currentDays + weekByFirstDay] = new Date(nextMonth.getFullYear(), nextMonth.getMonth(), i + 1);
                }

                return displayDays;
            };
            var getCellClass = function(date){
                var dateMonth = new Date(date.getFullYear(), date.getMonth(), 1);
                var currentMonth = new Date($scope.WindowDisplayMonth.getFullYear(), $scope.WindowDisplayMonth.getMonth(), 1);

                var returnClass;
                if(dateMonth < currentMonth){
                    returnClass = "PreMonthTD";
                }
                else if(dateMonth > currentMonth){
                    returnClass = "NextMonthTD";
                }
                else {
                    returnClass = "CurrentMonthTD";
                }

                if(valueDateTime.getFullYear() == date.getFullYear() &&
                    valueDateTime.getMonth() == date.getMonth() &&
                    valueDateTime.getDate() == date.getDate()){
                    returnClass += ' CurrentDateTD';
                }
                return returnClass;
            };
            var setCellsValue = function(days){
                for(var i=0; i<6; i++){
                    for(var j=0; j<7; j++){
                        var cell = $scope._BodyElement.rows[i + 1].cells[j];
                        var dayIndex = i * 7 + j;
                        cell.innerHTML = days[dayIndex].getDate();
                        cell.setAttribute('class', getCellClass(days[dayIndex]));
                    }
                }
            };

            $scope.cellClick = function(){
                var dayIndex = (event.srcElement.parentNode.rowIndex - 1) * 7 + event.srcElement.cellIndex;
                valueDateTime = new Date(windowDisplayDays[dayIndex].getFullYear(), windowDisplayDays[dayIndex].getMonth(), windowDisplayDays[dayIndex].getDate(),
                    valueDateTime.getHours(), valueDateTime.getMinutes(), valueDateTime.getSeconds());

                if($scope.value != valueDateTime.toString()){
                    isSetDateValue = true;
                    $scope.value = valueDateTime.toString();
                    $scope.WindowDisplayMonth = new Date(valueDateTime.getFullYear(), valueDateTime.getMonth(), 1);
                    $scope.DisplayText = BaseFunction.dateTimeToString(valueDateTime, $scope.Type);
                    $scope.$parent.$digest();
                    $scope.change();
                }
            };

            $scope.dateNowClick = function(){
                valueDateTime = new Date($scope.DateNow.getFullYear(), $scope.DateNow.getMonth(), $scope.DateNow.getDate(),
                    valueDateTime.getHours(), valueDateTime.getMinutes(), valueDateTime.getSeconds());

                if($scope.value != valueDateTime.toString()){
                    isSetDateValue = true;
                    $scope.value = valueDateTime.toString();
                    $scope.WindowDisplayMonth = new Date(valueDateTime.getFullYear(), valueDateTime.getMonth(), 1);
                    $scope.DisplayText = BaseFunction.dateTimeToString(valueDateTime, $scope.Type);
                    $scope.change();
                }
            };
            $scope.addMonth = function(qty){
                event.stopPropagation();
                //为了防止即将翻到的月份没有该日期做的处理，比如，当前月有31号，下个月没有，用30号显示，所以用1号代替计算
                var dateTime = new Date($scope.WindowDisplayMonth.getFullYear(), $scope.WindowDisplayMonth.getMonth(), 1);
                dateTime.setMonth($scope.WindowDisplayMonth.getMonth() + qty);
                $scope.WindowDisplayMonth = new Date(dateTime.getFullYear(), dateTime.getMonth(), 1);
                windowDisplayDays = getDisplayDays($scope.WindowDisplayMonth);
                setCellsValue(windowDisplayDays);
            };
            $scope.btnClick = function(){
                if(this.Enabled){
                    windowDisplayDays = getDisplayDays(valueDateTime);
                    setCellsValue(windowDisplayDays);

                    if(!$scope.IsFocuse){
                        $scope.IsFocuse = true;
                        document.addEventListener('click', $scope.BodyClick, true);
                    }
                }
            };

            var keyCodes = [32, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58];
            $scope.keyPress = function() {
                if(keyCodes.indexOf(event.keyCode) < 0) {
                    event.returnValue = false;
                }
            };

            var isDivClick = false;
            $scope.divClick = function(){
                isDivClick = true;
                $scope._InputElement.focus();
            };
            $scope.textFocus = function(){
                if(!isDivClick) {
                    $scope._InputElement.select();
                }
                isDivClick = false;

                if(!$scope.IsFocuse){
                    $scope.IsFocuse = true;
                    document.addEventListener('click', $scope.BodyClick, true);
                }
            };
            $scope.textChange = function(){
                var oldValue = $scope.value;
                if($scope.DisplayText != null && $scope.DisplayText != undefined && $scope.DisplayText.trim() != ""){
                    valueDateTime = BaseFunction.stringToDateTime($scope.DisplayText, $scope.Type);
                    if(valueDateTime){
                        $scope.WindowDisplayMonth = new Date(valueDateTime.getFullYear(), valueDateTime.getMonth(), 1);
                        $scope.DisplayText = BaseFunction.dateTimeToString(valueDateTime, $scope.Type);
                        $scope.value = valueDateTime.toString();
                    }
                    else{
                        valueDateTime = new Date();
                        $scope.WindowDisplayMonth = new Date();
                        $scope.DisplayText = '';
                        $scope.value = null;
                    }                    
                }
                else{
                    valueDateTime = new Date();
                    $scope.WindowDisplayMonth = new Date();
                    $scope.DisplayText = '';
                    $scope.value = null;
                }
                if($scope.value != oldValue){
                    isSetDateValue = true;
                }
                $scope.$parent.$digest();
                $scope.change();
            };
            $scope.keyDown = function(){
              $scope.keydown();
              if(event.keyCode == 13){
                  event.keyCode = 9;
              }
            };

            $scope.$watch(
                function(){
                    return $scope.value;
                },
                function() {
                    if(!isSetDateValue) {
                        if ($scope.value == undefined || $scope.value == null || $scope.value == '') {
                            valueDateTime = new Date();
                            $scope.WindowDisplayMonth = new Date();
                            $scope.DisplayText = '';
                        }
                        else if ($scope.value.constructor == String) {
                            if ($scope.value.trim() != '') {
                                $scope.WindowDisplayMonth = new Date($scope.value.trim());
                                valueDateTime = new Date($scope.WindowDisplayMonth.getFullYear(), $scope.WindowDisplayMonth.getMonth(), $scope.WindowDisplayMonth.getDate(),
                                    $scope.WindowDisplayMonth.getHours(), $scope.WindowDisplayMonth.getMinutes(), $scope.WindowDisplayMonth.getSeconds());
                                $scope.DisplayText = BaseFunction.dateTimeToString(valueDateTime, $scope.Type);
                            }
                            else {
                                $scope.value == undefined;
                                valueDateTime = BaseConst.DateTime.Min;
                                $scope.WindowDisplayMonth = new Date();
                                $scope.DisplayText = '';
                            }
                        }
                        else if ($scope.value.constructor == Date) {
                            $scope.WindowDisplayMonth = new Date($scope.value.getFullYear(), $scope.value.getMonth(), 1);
                            valueDateTime = new Date($scope.value.getFullYear(), $scope.value.getMonth(), $scope.value.getDate(),
                                $scope.value.getHours(), $scope.value.getMinutes(), $scope.value.getSeconds());
                            $scope.value = $scope.value.toString();
                            $scope.DisplayText = BaseFunction.dateTimeToString(valueDateTime, $scope.Type);
                        }
                    }
                    else{
                        isSetDateValue = false;
                    }
                }
            );
        }],
        link: function (scope, element, attrs) {
            scope.Enabled = true;
            scope.Visible = true;
            scope.IsFocuse = false;
            scope.IsWindowDisplay = false;
            scope.Type = BaseEnum.DateTimeFormat.DateTime;
            scope.IsGrid = false;
            scope._InputElement = element[0].children[0];
            scope._DivElement = element[0].children[2];
            scope._BodyElement = element[0].children[2].children[0].rows[1].cells[0].children[0].children[0];

            if (attrs["type"] != undefined && attrs["type"].toLocaleLowerCase().trim() == "date") {
                scope.Type = BaseEnum.DateTimeFormat.Date;
            }
            if (attrs["isgrid"] != undefined && attrs["isgrid"].toLocaleLowerCase() == "true") {
                scope.IsGrid = true;
                element[0].children[0].setAttribute("class", "form-control BaseControl GridBaseControl");
                element[0].children[1].children[0].setAttribute("class", "btn btn-default BaseControl CalendarBtn GridBaseControl");
            }

            for(var i=1; i<7; i++){
                for(var j=0; j<7; j++){
                    scope._BodyElement.rows[i].cells[j].addEventListener('click', scope.cellClick, false);
                }
            }

            scope.BodyClick = function(){
                if(scope.IsFocuse) {
                    var eventNode = event.srcElement;

                    while(eventNode){
                        if(eventNode == document ||eventNode == undefined || eventNode.tagName == undefined ||
                            eventNode.tagName.toLowerCase() == 'html' || eventNode.tagName.toLowerCase() == 'body'){
                            scope.IsFocuse = false;
                            document.removeEventListener('click', scope.BodyClick, true);
                            scope.blur();
                            break;
                        }
                        else if(eventNode == element[0]) {
                            break;
                        }
                        eventNode = eventNode.parentNode;
                    }
                }
            };

            scope._InputElement.addEventListener('change', function(){scope.$apply(scope.textChange())}, false);

            scope.$watch(
                function(){
                    return attrs["enabled"];
                },
                function(){
                    if (attrs["enabled"] != undefined && attrs["enabled"].trim().toLocaleLowerCase() == "false") {
                        scope.Enabled = false;
                    }
                    else{
                        scope.Enabled = true;
                    }
                }
            );

            scope.$watch(
                function(){
                    return attrs["visible"]
                },
                function(){
                    if (attrs["visible"] != undefined && attrs["visible"].trim().toLocaleLowerCase() == "false") {
                        scope.Visible = false;
                    }
                    else{
                        scope.Visible = true;
                    }
                }
            );
        }
    }
}]);
